﻿
#region 文件信息
/*----------------------------------------------------------------
// 
// 文件名称：	
// 文件功能描述：	
// 设计要求：	
//
// 文 件 名：    VampirewalHttpClientService
// 创建者：      杨程
// 创建日期：	    2022/11/14 15:20:57

//----------------------------------------------------------------*/
#endregion

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Text.Json.Serialization;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace Vampirewal.Core.HttpClientService;

/// <summary>
/// 
/// </summary>
public class VampirewalHttpClientService : IHttpClientService
{

    #region 配置
    public ServiceProvider ServiceProvider { get; private set; }
    public IServiceCollection serviceCollection { get; private set; }

    public JsonSerializerOptions options { get; private set; }

    public VampirewalHttpClientService()
    {
        serviceCollection = new ServiceCollection();
        ServiceProvider = serviceCollection.AddHttpClient().BuildServiceProvider();
        ConfigureServices(serviceCollection);

        _httpClientFactory = ServiceProvider.GetService<IHttpClientFactory>();


    }

    private void ConfigureServices(IServiceCollection services)
    {
        //services.AddHttpClient();
        //ServiceProvider = services.BuildServiceProvider();
    }

    public Dictionary<string, string> RequestHeaderDic { get; private set; } = new Dictionary<string, string>();

    /// <summary>
    /// 设置请求头
    /// </summary>
    /// <param name="_requestHeaderDic"></param>
    public void SetHeader(Dictionary<string, string> _requestHeaderDic)
    {
        RequestHeaderDic = _requestHeaderDic;
    }


    [Obsolete("暂时不可用", true)]
    public void AddHttpClient(string ClientName, Dictionary<string, string> RequestHeaderDic)
    {
        serviceCollection.AddHttpClient("aaa", c =>
        {

        });
    }

    /// <summary>
    /// 设置自定义反序列化设置
    /// </summary>
    /// <param name="options"></param>
    public void SetJsonSerializerOptions(JsonSerializerOptions options)
    {
        this.options = options;
    }
    #endregion


    protected IHttpClientFactory _httpClientFactory { get; set; }


    private HttpClient CreateClient(string url)
    {
        if (url.StartsWith("https"))
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
        }

        var _httpClient = _httpClientFactory.CreateClient();

        if (RequestHeaderDic.Count > 0)
        {
            foreach (var item in RequestHeaderDic)
            {
                _httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
            }
        }

        return _httpClient;
    }

    #region GET请求
    /// <summary>
    /// GET请求
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public string HttpGet(string url)
    {
        string result = "";

        var _httpClient = CreateClient(url);

        var response = _httpClient.GetAsync(url).Result;

        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                result = t.Result;
            }
        }
        return result;
    }

    /// <summary>
    /// GET请求(返回对象)
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public T HttpGet<T>(string url)
    {
        var _httpClient = CreateClient(url);

        var response = _httpClient.GetAsync(url).Result;

        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                //options.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); //解决中文序列化被编码的问题
                //options.Converters.Add(new DateTimeConverter()); //解决时间格式序列化的问题

                return JsonSerializer.Deserialize<T>(t.Result, options);
            }
        }
        return default(T);
    }

    public async Task<bool> HttpGetDownLoad(string url, string SavePath)
    {
        var _httpClient = CreateClient(url);

        HttpResponseMessage response = _httpClient.GetAsync(url).Result;
        response.EnsureSuccessStatusCode();
        if (response.IsSuccessStatusCode)
        {
            using (FileStream fs = File.Open(SavePath, FileMode.Create))
            {
                using Stream ms = response.Content.ReadAsStream();
                await ms.CopyToAsync(fs);
            }

            return true;
        }

        return false;
    }

    public string RequestGetOfCustomParameter(string url, params RequestParam[] requestParams)
    {
        string result = "";
        var _httpClient = CreateClient(url);

        string UrlAndParamStr = "";

        if (requestParams!=null&& requestParams.Count()>0)
        {
            List<string> ParamList = new List<string>();
            foreach (var item in requestParams)
            {
                ParamList.Add(item.RequestString);
            }
            UrlAndParamStr = $"{url}?{string.Join("&", ParamList)}";
        }
        else
        {
            UrlAndParamStr = $"{url}";
        }


        var response = _httpClient.GetAsync(UrlAndParamStr).Result;

        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                result = t.Result;
            }
        }
        return result;
    }

    public T RequestGetOfCustomParameter<T>(string url, params RequestParam[] requestParams)
    {
        var _httpClient = CreateClient(url);

        string UrlAndParamStr = "";

        if (requestParams != null && requestParams.Count() > 0)
        {
            List<string> ParamList = new List<string>();
            foreach (var item in requestParams)
            {
                ParamList.Add(item.RequestString);
            }
            UrlAndParamStr = $"{url}?{string.Join("&", ParamList)}";
        }
        else
        {
            UrlAndParamStr = $"{url}";
        }

        var response = _httpClient.GetAsync(UrlAndParamStr).Result;

        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                return JsonSerializer.Deserialize<T>(t.Result, options);
            }
        }
        return default(T);
    }
    #endregion

    #region POST请求--异步方法

    /// <summary>
    /// POST请求
    /// </summary>
    /// <param name="url">API地址</param>
    /// <param name="obj">传递的参数</param>
    /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
    /// <param name="charset"></param>
    /// <returns>Json文本</returns>       
    public string HttpPost(string url, object obj, ContentType contentType, string charset = "UTF-8")
    {
        string result = "";
        var _httpClient = CreateClient(url);

        _httpClient.DefaultRequestHeaders.Accept.Clear();
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType.GetDisplay()));

        string content = JsonSerializer.Serialize(obj);

        var httpContent = new StringContent(content, Encoding.UTF8, contentType.GetDisplay());

        var response = _httpClient.PostAsync(url, httpContent).Result;
        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                result = t.Result;
            }
        }
        return result;
    }

    public string RequestPostOfCustomParameter(string url, params RequestParam[] requestParams)
    {
        string result = "";
        var _httpClient = CreateClient(url);

        string UrlAndParamStr = "";

        if (requestParams != null && requestParams.Count() > 0)
        {
            List<string> ParamList = new List<string>();
            foreach (var item in requestParams)
            {
                ParamList.Add(item.RequestString);
            }
            UrlAndParamStr = $"{url}?{string.Join("&", ParamList)}";
        }
        else
        {
            UrlAndParamStr = $"{url}";
        }

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, UrlAndParamStr);

        var response = _httpClient.SendAsync(request).Result;

        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                result = t.Result;
            }
        }
        return result;
    }

    public T RequestPostOfCustomParameter<T>(string url, params RequestParam[] requestParams)
    {
        var _httpClient = CreateClient(url);

        string UrlAndParamStr = "";

        if (requestParams != null && requestParams.Count() > 0)
        {
            List<string> ParamList = new List<string>();
            foreach (var item in requestParams)
            {
                ParamList.Add(item.RequestString);
            }
            UrlAndParamStr = $"{url}?{string.Join("&", ParamList)}";
        }
        else
        {
            UrlAndParamStr = $"{url}";
        }

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, UrlAndParamStr);

        var response = _httpClient.SendAsync(request).Result;

        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                return JsonSerializer.Deserialize<T>(t.Result, options);
            }
            else
            {
                return default(T);
            }
        }
        else
        {
            return default(T);
        }
    }

    /// <summary>
    /// POST请求(返回对象)
    /// </summary>
    /// <param name="url">API地址</param>
    /// <param name="obj">传递的参数</param>
    /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
    /// <param name="charset"></param>
    /// <returns>对象</returns>       
    public T HttpPost<T>(string url, object obj, ContentType contentType, string charset = "UTF-8")
    {
        var _httpClient = CreateClient(url);

        _httpClient.DefaultRequestHeaders.Accept.Clear();
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType.GetDisplay()));

        string content = JsonSerializer.Serialize(obj);

        var httpContent = new StringContent(content, Encoding.UTF8, contentType.GetDisplay());

        var response = _httpClient.PostAsync(url, httpContent).Result;
        if (response.IsSuccessStatusCode)
        {
            Task<string> t = response.Content.ReadAsStringAsync();
            if (t != null)
            {
                return JsonSerializer.Deserialize<T>(t.Result, options);
            }
            else
            {
                return default(T);
            }
        }
        else
        {
            return default(T);
        }

    }

    /// <summary>
    /// 通过POST模拟表单调用上传图片
    /// </summary>
    /// <param name="uploadUrl">请求地址</param>
    /// <param name="imgPath">图片路径</param>
    /// <param name="Param">表单参数</param>
    /// <param name="fileparameter"></param>
    /// <returns></returns>
    public async Task<string> PostUploadImage(string uploadUrl, string imgPath, Dictionary<string, string> Param = null, string fileparameter = "file")
    {
        var httpClient = CreateClient(uploadUrl);

        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/JOSN"));//设定要响应的数据格式

        using (MultipartFormDataContent httpContent = new MultipartFormDataContent())
        {
            using (var fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(imgPath)))
            {
                //int pos = imgPath.LastIndexOf("/");
                //string fileName = imgPath.Substring(pos + 1);
                string fileName = Path.GetFileName(imgPath);
                httpContent.Add(fileContent, fileparameter, fileName);

                if (Param != null && Param.Count > 0)
                {
                    foreach (var (key, value) in Param)
                    {
                        var valueBytes = Encoding.UTF8.GetBytes(value);
                        var byteArray = new ByteArrayContent(valueBytes);
                        byteArray.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                        {
                            Name = key
                        };
                        httpContent.Add(byteArray);
                    }
                }


                var response = await httpClient.PostAsync(uploadUrl, httpContent);

                if (response.IsSuccessStatusCode)
                {
                    string result = await response.Content.ReadAsStringAsync();
                    return result;
                }
                return null;
            }

        }
    }

    public async Task<string> FormRequestPost(string url, RequestParam[] requestParams)
    {
        if (requestParams == null)
        {
            throw new Exception("请求参数不能为null！");
        }

        var httpClient = CreateClient(url);

        using (MultipartFormDataContent httpContent = new MultipartFormDataContent())
        {
            foreach (var item in requestParams)
            {
                var valueBytes = Encoding.UTF8.GetBytes(item.RequestValue.ToString());
                var byteArray = new ByteArrayContent(valueBytes);
                byteArray.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                {
                    Name = item.RequestParameterName
                };
                httpContent.Add(byteArray);
            }

            var response = await httpClient.PostAsync(url, httpContent);

            if (response.IsSuccessStatusCode)
            {
                string result = await response.Content.ReadAsStringAsync();
                return result;
            }
            return null;
        }

    }

    #endregion
}






/// <summary>
/// 
/// </summary>
public class Token
{
    public string access_token { get; set; }

    public int expires_in { get; set; }

    public string token_type { get; set; }

    public string refresh_token { get; set; }
}

/// <summary>
/// 传输类型枚举
/// </summary>
public enum ContentType
{
    [Display(Name = "application/xml")]
    application_xml = 0,
    [Display(Name = "application/json")]
    application_json = 1,
    [Display(Name = "application/text")]
    application_text = 2,
    [Display(Name = "application/x-www-form-urlencoded")]
    application_x_www_form_urlencoded = 3
}

public class DateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
    }
}

public class DateTimeNullableConverter : JsonConverter<DateTime?>
{
    public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return string.IsNullOrEmpty(reader.GetString()) ? default(DateTime?) : DateTime.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value?.ToString("yyyy-MM-dd HH:mm:ss"));
    }
}

/// <summary>
/// 枚举扩展类
/// </summary>
internal static class EnumHelper
{
    /// <summary>
    /// 获取枚举的Display文本
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static String GetDisplay(this Enum value)
    {
        var type = value.GetType();//先获取这个枚举的类型
        var field = type.GetField(value.ToString());//通过这个类型获取到值
        var obj = (DisplayAttribute)field.GetCustomAttribute(typeof(DisplayAttribute));//得到特性
        return obj.Name ?? "";
    }
}
